在Day7介紹了wakelock, 讓系統暫時不會進入休眠
而會使用到wakelock的時間點, 往往都是接收到了某個intent
然後藉由intent去開啟service做相對應的任務,
並且在service啟動時取得wakelock, 結束時釋放wakelock
Android SDK針對這個需求提供了一個方便的class: WakefulBroadcastReceiver
這個class繼承原本的BroadcastReceiver, 並且可以幫助我們管理wakelock
使用方式如下:
繼承WakefulBroadcastReceiver, 並且收到intent後使用startWakefulService()
開啟service(這裡使用IntentService)
MyWakefulReceiver.java
public class MyWakefulReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MyIntentService.class);
startWakefulService(context, serviceIntent);
}
}
SimpleWakefulService.java
public class SimpleWakefulService extends IntentService {
public SimpleWakefulService() {
super("SimpleWakefulService");
}
@Override
protected void onHandleIntent(Intent intent) {
for (int i=0; i<5; i++) {
Log.i("SimpleWakefulReceiver", "Running service " + (i+1)
+ "/5 @ " + SystemClock.elapsedRealtime());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
SimpleWakefulReceiver.completeWakefulIntent(intent);
}
}
這樣就完全看不到wakelock的管理了吧!
但別忘了因為是WakefulBroadcastReceiver 幫你取得wakelock,
因此還是需要在AndroidManifest.xml宣告wakelock permission
<uses-permission android:name="android.permission.WAKE_LOCK" />
以及宣告這兩個class
<receiver android:name=".MyWakefulReceiver"></receiver>
<service android:name=".SimpleWakefulService"></service>
P.S.
看看WakefulBroadcastReceiver和原本的BroadcastReceiver有甚麼不同:
public abstract class WakefulBroadcastReceiver extends BroadcastReceiver {
private static final String EXTRA_WAKE_LOCK_ID = "android.support.content.wakelockid";
private static final SparseArray<PowerManager.WakeLock> mActiveWakeLocks
= new SparseArray<PowerManager.WakeLock>();
private static int mNextId = 1;
public static ComponentName startWakefulService(Context context, Intent intent) {
synchronized (mActiveWakeLocks) {
int id = mNextId;
mNextId++;
if (mNextId <= 0) {
mNextId = 1;
}
intent.putExtra(EXTRA_WAKE_LOCK_ID, id);
ComponentName comp = context.startService(intent);
if (comp == null) {
return null;
}
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"wake:" + comp.flattenToShortString());
wl.setReferenceCounted(false);
wl.acquire(60*1000);
mActiveWakeLocks.put(id, wl);
return comp;
}
}
public static boolean completeWakefulIntent(Intent intent) {
final int id = intent.getIntExtra(EXTRA_WAKE_LOCK_ID, 0);
if (id == 0) {
return false;
}
synchronized (mActiveWakeLocks) {
PowerManager.WakeLock wl = mActiveWakeLocks.get(id);
if (wl != null) {
wl.release();
mActiveWakeLocks.remove(id);
return true;
}
Log.w("WakefulBroadcastReceiver", "No active wake lock id #" + id);
return true;
}
}
}
其實就只是多了startWakefulService(), completeWakefulIntent()這兩個method
startWakefulService負責開啟service並且取得wakelock(注意有時限為60秒)
completeWakefulIntent則是負責釋放wakelock
reference:
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html
https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/v4/java/android/support/v4/content/WakefulBroadcastReceiver.java